/******************************************************************************

           Copyright @2024 - 2044 Shenzhen dcenzix Technology Ltd.

 ******************************************************************************
@file cola_os.c
@brief cola系统
@author xiexiongwu
@version V1.0
@date 2024年5月25日

******************************************************************************/

/*----------------------------------------------*
 * 包含头文件                                   *
 *----------------------------------------------*/
#include <stdio.h>
#include <stdint.h>
#include "cola_os.h"

#include "s32_core_cm0.h"


#if 0
//in keil arm gcc
#define disable_irq()  __disable_irq()
#define enable_irq()   __enable_irq()

#define OS_CPU_SR   uint32_t
#define enter_critical()        \
    do { cpu_sr = __get_PRIMASK(); __disable_irq();} while (0)
#define exit_critical()         \
    do { __set_PRIMASK(cpu_sr);} while (0)
#else

/* 替换后的中断控制宏 */
#define disable_irq()  DISABLE_INTERRUPTS()
#define enable_irq()   ENABLE_INTERRUPTS()

/* 定义临界区保护类型 */
#define OS_CPU_SR uint32_t

/* 临界区保护宏（适配GCC） */
#define enter_critical() \
do					\
{                     \
    __asm volatile ("mrs %0, primask" : "=r" (cpu_sr)); \
    disable_irq();       \
} while (0)

#define exit_critical()  \
do					\
{                     \
    __asm volatile ("msr primask, %0" : : "r" (cpu_sr)); \
} while (0)
#endif




/*----------------------------------------------*
 * 宏定义                                 *
 *----------------------------------------------*/
#define LIST_HEAD_INIT(name) { 0 }

#define TASK_LIST_HEAD(name) \
    struct task_s name = LIST_HEAD_INIT(name)

#define list_for_each(pos, head) \
    for (pos = (head)->next; pos != NULL; pos = pos->next)

#define list_for_null(pos, head) \
    for (pos = head; pos->next != NULL; pos = pos->next)

#define list_for_each_safe(pos, n, head) \
    for (pos = (head)->next; pos != NULL; \
            n = pos->next,pos = n)

#define list_for_each_del(pos, n, head) \
    for (n = (head),pos = (head)->next; pos != NULL; \
            n = pos,pos = pos->next)

#define time_after_eq(a,b)  (((int)((a) - (b)) >= 0))

/*----------------------------------------------*
 * 枚举定义                                         *
 *----------------------------------------------*/

/*----------------------------------------------*
 * 全局变量                                         *
 *----------------------------------------------*/
/** \var task_list
 *  \brief 任务队列初始化
 */
static TASK_LIST_HEAD(task_list);

/** \var jiffies
 *	\brief 计时器
 */

volatile uint32_t jiffies = 0;

/** \var jiffies
 *	\brief 计时器
 */

/*----------------------------------------------*
 * 函数原型说明                                       *
 *----------------------------------------------*/

/*
  循环遍历任务链表
*/
/**
 *@brief 循环遍历任务链表
 *
 *@param [in]void
 *@return void
 *
 */
void cola_task_loop(void)
{
    uint32_t events = 0;
    task_t *cur, *n = NULL ;
    OS_CPU_SR cpu_sr;

    list_for_each_safe(cur, n, &task_list)
    {
        //检查定时任务是否超时
        if ((EN_COLA_TASK_TIMER == cur->taskType) && (cur->start) && (time_after_eq(jiffies, cur->timerTick)))
        {
            enter_critical();
            cur->run = true;
            cur->timerTick = jiffies + cur->period;
            exit_critical();
        }
        if (cur->run)
        {
            if ((EN_COLA_TIMER_ONE_SHOT == cur->timerType) && (EN_COLA_TASK_TIMER == cur->taskType))
            {
                cur->start = false;
            }
            if (NULL != cur->func)
            {
                events = cur->event;
                if (events)
                {
                    enter_critical();
                    cur->event = 0;
                    exit_critical();
                }
                cur->func(cur->usr, events);
            }
            if (EN_COLA_TASK_TIMER == cur->taskType)
            {
                enter_critical();
                cur->run = false;
                exit_critical();
            }

        }
    }
}


/**
 *@brief 查找任务是否存在
 *
 *@param [in]task_t *task  任务
 *@return bool true:任务存在;false:任务不存在
 *
 */
bool cola_task_is_exists(task_t *task)
{
    task_t *cur ;
    list_for_each(cur, &task_list)
    {
        if (cur->taskNum == task->taskNum)
        {
            return true;
        }
    }
    return false;
}

/**
 *@brief 创建任务
 *
 *@param [in]task_t *task  任务
 *@param [in]cbFunc func   任务回调函数
 *@param [in]void *arg     传入参数
 *@return bool true:任务创建成功;false:任务创建失败
 *
 */
bool cola_task_create(task_t *task, cbFunc func, void *arg)
{
    task_t *cur  ;
    OS_CPU_SR cpu_sr;
    enter_critical();
    if ((NULL == task) || (cola_task_is_exists(task)))
    {
        exit_critical();
        return false;
    }
    task->taskType  = EN_COLA_TASK_TASK;
    task->start     = true;
    task->run       = true;
    task->func      = func;
    task->event     = 0;
    task->usr       = arg;
    list_for_null(cur, &task_list)
    {

    }
    task->taskNum = cur->taskNum + 1;
    cur->next  = task;
    task->next = NULL;
    exit_critical();
    return true;
}

/**
 *@brief 删除指定任务
 *
 *@param [in]task_t *task  任务
 *@return bool true:任务创建成功;false:任务创建失败
 *
 */
bool cola_task_delete(task_t *task)
{
    task_t *cur, *n;
    OS_CPU_SR cpu_sr;
    enter_critical();
    list_for_each_del(cur, n, &task_list)
    {
        if (cur->taskNum == task->taskNum)
        {
            n->next = cur->next;
            exit_critical();
            return true;
        }
    }
    exit_critical();
    return false;
}

/**
 *@brief 定时器任务创建
 *
 *@param [in]task_t *task  任务
 *@param [in]cbFunc func   任务回调函数
 *@param [in]void *arg     传入参数
 *@return bool true:任务创建成功;false:任务创建失败
 *
 */

bool cola_timer_create(task_t *timer, cbFunc func, void *arg)
{
    task_t *cur ;

    OS_CPU_SR cpu_sr;
    enter_critical();
    if ((NULL == timer) || (cola_task_is_exists(timer)))
    {
        exit_critical();
        return false;
    }
    timer->taskType  = EN_COLA_TASK_TIMER;
    timer->run       = false;
    timer->period    = 0;
    timer->timerType = EN_COLA_TIMER_ONE_SHOT;
    timer->start     = false;
    timer->timerTick = 0;
    timer->func      = func;
    timer->event     = 0;
    timer->usr       = arg;

    list_for_null(cur, &task_list)
    {

    }
    timer->taskNum = cur->taskNum + 1;
    cur->next   = timer;
    timer->next = NULL;
    exit_critical();
    return true;

}

/**
 *@brief 定时器任务启动
 *
 *@param [in]task_t *timer  任务
 *@param [in]cbFunc func   任务回调函数
 *@param [in]void *arg     传入参数
 *@return bool true:任务创建成功;false:任务创建失败
 *
 */
bool cola_timer_start(task_t *timer, EN_COLA_TIMER_TYPE time_type, uint32_t time_ms)
{
    task_t *cur ;
    OS_CPU_SR cpu_sr;
    enter_critical();
    list_for_each(cur, &task_list)
    {
        if (cur->taskNum == timer->taskNum)
        {
            timer->period    = time_ms;
            timer->timerType = time_type;
            timer->start     = true;
            timer->timerTick = jiffies + time_ms;
            timer->taskType  = EN_COLA_TASK_TIMER;
            exit_critical();
            return true;
        }
    }
    exit_critical();
    return false;
}

/**
 *@brief 定时器停止
 *
 *@param [in]task_t *timer  任务
 *@return bool true:定时器停止成功;false:定时器停止失败
 *
 */

bool cola_timer_stop(task_t *timer)
{
    task_t *cur;
    OS_CPU_SR cpu_sr;
    enter_critical();
    list_for_each(cur, &task_list)
    {
        if (cur->taskNum == timer->taskNum)
        {
            timer->start = false;
            exit_critical();
            return true;
        }
    }
    exit_critical();
    return false;
}
/**
 *@brief 删除指定定时器任务
 *
 *@param [in]task_t *timer  任务
 *@return bool true:定时器删除成功;false:定时器删除失败
 *
 */


bool cola_timer_delete(task_t *timer)
{
    return cola_task_delete(timer);
}

/**
 *@brief 定时计数器(uint ms)
 *
 *@param void
 *@return void
 *
 */
void cola_timer_ticker(void)
{
    jiffies++;
}

/**
 *@brief 获取tick count(uint ms)
 *
 *@param void
 *@return tick count
 *
 */
unsigned int cola_get_ticker(void)
{
    return jiffies;
}


/**
 *@brief 设置任务事件
 *
 *@param [in]task_t *task  任务
 *@param [in]EN_COLA_EVENT_TYPE event 事件
 *@return bool true:设置任务成功;false:设置任务失败
 *
 */
bool cola_set_event(task_t *task, uint32_t event)
{
    task_t *cur;
    OS_CPU_SR cpu_sr;
    enter_critical();
    list_for_each(cur, &task_list)
    {
        if (cur->taskNum == task->taskNum)
        {
            cur->event |= event;
            exit_critical();
            return true;
        }
    }
    exit_critical();
    return false;
}
/**
 *@brief 清除任务事件
 *
 *@param [in]task_t *task  任务
 *@param [in]EN_COLA_EVENT_TYPE event 事件
 *@return bool true:清除任务成功;false:清除任务失败
 *
 */
bool cola_clear_event(task_t *task, uint32_t event)
{
    task_t *cur;
    OS_CPU_SR cpu_sr;
    enter_critical();
    list_for_each(cur, &task_list)
    {
        if (cur->taskNum == task->taskNum)
        {
            cur->event &= ~(event);
            exit_critical();
            return true;
        }
    }
    exit_critical();
    return false;
}

/**
 *@brief 任务延时
 *
 *@param [in]uint32_t ms  任务延时时间
 *@return void
 *
 */
void cola_delay_ms(uint32_t ms)
{
    unsigned int start = jiffies;
    while ((jiffies - start) <= ms);
}


